﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace Uhi.Applications.FileAid.Interactivity
{
    #region ListSelectBehavior
    /// <summary>
    /// <see cref="System.Windows.Controls.ListBox"/> 上の <see cref="System.Windows.Controls.TextBox"/> が
    /// フォーカスされたとき、その行を選択状態にする <see cref="Behavior"/>。
    /// </summary>
    public class ListSelectBehavior : Behavior<ListBox>
    {
        #region OnAttached
        /// <summary>
        /// <see cref="Behavior.AssociatedObject"/> に機能をフックアップする。
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.GotFocus += this.GotFocus;
        }
        #endregion

        #region OnDetaching
        /// <summary>
        /// <see cref="Behavior.AssociatedObject"/> から機能をアンフックする。
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.GotFocus -= this.GotFocus;
        }
        #endregion

        #region GotFocus
        /// <summary>
        /// <see cref="System.Windows.Controls.ListBox"/> 上の <see cref="System.Windows.Controls.TextBox"/> が
        /// フォーカスされたとき、その行を選択状態にする。
        /// </summary>
        /// <param name="sender">イベントソース。</param>
        /// <param name="e">イベントデータ。</param>
        private void GotFocus(object sender, RoutedEventArgs e)
        {
            var listbox = this.AssociatedObject;
            var element = FocusManager.GetFocusedElement(this.GetWindow(listbox)) as DependencyObject;
            var container = listbox.ContainerFromElement(element);

            if (container == null)
                return;

            var index = listbox.ItemContainerGenerator.IndexFromContainer(container);
            listbox.SelectedIndex = index;
        }
        #endregion

        #region GetWindow
        /// <summary>
        /// 指定した <see cref="DependencyObject"/> を所有する <see cref="Window"/> を取得する。
        /// </summary>
        /// <param name="obj">任意の <see cref="DependencyObject"/>。</param>
        /// <returns>指定した <see cref="DependencyObject"/> を所有する <see cref="Window"/>。</returns>
        private Window GetWindow(DependencyObject obj)
        {
            if (obj is Window || obj == null)
                return obj as Window;
            else
                return this.GetWindow(VisualTreeHelper.GetParent(obj));
        }
        #endregion
    }
    #endregion
}
